﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq;
using System.Diagnostics;
using System.Text;
using System.IO;
using USB2XXX;
/**
 * 注意：若运行程序提示找不到USB2XXX.dll文件，可以将工程目录下的USB2XXX.dll和libusb-1.0.dll文件拷贝到exe程序输出目录下即可（一般是./bin/Release或者./bin/Debug目录）
 * 运行程序之前，先将CAN1_H接CAN2_H，CAN1_L接CAN2_L，可以直接测试CAN1和CAN2之间的数据收发情况
 */
namespace USB2XXX_CAN_DBCParserTest
{
    class Program
    {
        static void Main(string[] args)
        {
            USB_DEVICE.DEVICE_INFO DevInfo = new USB_DEVICE.DEVICE_INFO();
            Int32[] DevHandles = new Int32[20];
            Int32 DevHandle = 0;
            Byte WriteCANIndex = 0;
            Byte ReadCANIndex = 1;
            bool state;
            Int32 DevNum, ret;
            string dllFilePath = "USB2XXX.dll";
            if (!File.Exists(dllFilePath))
            {
                Console.WriteLine("请先将USB2XXX.dll和libusb-1.0.dll文件复制到exe程序文件输出目录下!");
                Console.WriteLine("dll文件在‘usb2can_lin_pwm_example/sdk/libs/windows’目录下！");
                Console.WriteLine("程序是32位的就复制‘x86’目录下文件，程序是64位的就复制‘x86_64’目录下文件！");
                return;
            }
            //扫描查找设备，并将每个设备的唯一设备号存放到数组中，后面的函数需要用到
            DevNum = USB_DEVICE.USB_ScanDevice(DevHandles);
            if (DevNum <= 0)
            {
                Console.WriteLine("No device connected!");
                return;
            }
            else
            {
                Console.WriteLine("Have {0} device connected!", DevNum);
            }
            DevHandle = DevHandles[0];//获取第一个设备的设备号
            //打开设备
            state = USB_DEVICE.USB_OpenDevice(DevHandle);
            if (!state)
            {
                Console.WriteLine("Open device error!");
                return;
            }
            else
            {
                Console.WriteLine("Open device success!");
            }
            //获取固件信息
            StringBuilder FuncStr = new StringBuilder(256);
            state = USB_DEVICE.DEV_GetDeviceInfo(DevHandle, ref DevInfo, FuncStr);
            if (!state)
            {
                Console.WriteLine("Get device infomation error!");
                return;
            }
            else
            {
                Console.WriteLine("Firmware Info:");
                Console.WriteLine("    Name:" + Encoding.Default.GetString(DevInfo.FirmwareName));
                Console.WriteLine("    Build Date:" + Encoding.Default.GetString(DevInfo.BuildDate));
                Console.WriteLine("    Firmware Version:v{0}.{1}.{2}", (DevInfo.FirmwareVersion >> 24) & 0xFF, (DevInfo.FirmwareVersion >> 16) & 0xFF, DevInfo.FirmwareVersion & 0xFFFF);
                Console.WriteLine("    Hardware Version:v{0}.{1}.{2}", (DevInfo.HardwareVersion >> 24) & 0xFF, (DevInfo.HardwareVersion >> 16) & 0xFF, DevInfo.HardwareVersion & 0xFFFF);
                Console.WriteLine("    Functions:" + DevInfo.Functions.ToString("X8"));
                Console.WriteLine("    Functions String:" + FuncStr);
                StringBuilder DLLBuildDate = new StringBuilder(256);
                USB_DEVICE.DEV_GetDllBuildTime(DLLBuildDate);
                Console.WriteLine("    DLL Build Date:" + DLLBuildDate);
            }
            Console.WriteLine("");
            //获取CAN波特率参数
            USB2CAN.CAN_INIT_CONFIG CANConfig = new USB2CAN.CAN_INIT_CONFIG();
            ret = USB2CAN.CAN_GetCANSpeedArg(DevHandle, ref CANConfig, 500000);
            if (ret != USB2CAN.CAN_SUCCESS)
            {
                Console.WriteLine("Get CAN Speed failed!");
                return;
            }
            else
            {
                Console.WriteLine("Get CAN Speed Success!");
            }
            CANConfig.CAN_Mode = 0x80;//正常模式并接入终端电阻
            ret = USB2CAN.CAN_Init(DevHandle, WriteCANIndex, ref CANConfig);
            if (ret != USB2CAN.CAN_SUCCESS)
            {
                Console.WriteLine("Config CAN failed!");
                return;
            }
            else
            {
                Console.WriteLine("Config CAN Success!");
            }
            //初始化CAN
            ret = USB2CAN.CAN_Init(DevHandle, ReadCANIndex, ref CANConfig);
            if (ret != USB2CAN.CAN_SUCCESS)
            {
                Console.WriteLine("Config CAN failed!");
                return;
            }
            else
            {
                Console.WriteLine("Config CAN Success!");
            }
            Console.WriteLine("");
            //解析DBC文件
            UInt64 DBCHandle = DBCParser.DBC_ParserFile(DevHandle, new StringBuilder("Common_DBC.dbc"));
            if(DBCHandle==0){
                Console.WriteLine("Parser DBC File error!");
                return;
            }else{
                Console.WriteLine("Parser DBC File success!");
            }
            //打印DBC里面报文和信号相关信息
            int DBCMsgNum = DBCParser.DBC_GetMsgQuantity(DBCHandle);
            for(int i=0;i<DBCMsgNum;i++) {
                StringBuilder MsgName = new StringBuilder(32);
                DBCParser.DBC_GetMsgName(DBCHandle,i,MsgName);
                Console.WriteLine("Msg.Name = {0}",MsgName);
                int DBCSigNum = DBCParser.DBC_GetMsgSignalQuantity(DBCHandle,MsgName);
                Console.Write("Signals:");
                for(int j=0;j<DBCSigNum;j++) {
                    StringBuilder SigName = new StringBuilder(32);
                    DBCParser.DBC_GetMsgSignalName(DBCHandle,MsgName,j,SigName);
                    Console.Write("{0} ", SigName);
                }
                Console.WriteLine("");
            }
            USB2CAN.CAN_MSG[] CanMsg = new USB2CAN.CAN_MSG[3];
            for(int i=0;i<CanMsg.Length;i++){
                CanMsg[i] = new USB2CAN.CAN_MSG();
                CanMsg[i].Data = new Byte[8];
            }
            //设置信号值
            DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), 2412);
            DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), 980);
            DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), 120);
            //将信号值填入CAN消息里面
            IntPtr msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)));
            DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder("msg_moto_speed"), msgPt);
            CanMsg[0] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CAN.CAN_MSG));

            DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder("msg_oil_pressure"), msgPt);
            CanMsg[1] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CAN.CAN_MSG));

            DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder("msg_speed_can"), msgPt);
            CanMsg[2] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CAN.CAN_MSG));
            //释放申请的临时缓冲区
            Marshal.FreeHGlobal(msgPt);
            Console.WriteLine("");
            //发送CAN数据
            int SendedNum = USB2CAN.CAN_SendMsg(DevHandle,WriteCANIndex,CanMsg,(UInt32)CanMsg.Length);
            if(SendedNum >= 0){
                Console.WriteLine("Success send frames:{0}",SendedNum);
            }else{
                Console.WriteLine("Send CAN data failed! {0}",SendedNum);
            }

            //另外一个CAN通道读取数据
            USB2CAN.CAN_MSG[] CanMsgBuffer = new USB2CAN.CAN_MSG[10];
            msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)) * CanMsgBuffer.Length);
            int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle,ReadCANIndex,msgPt,CanMsgBuffer.Length);
            if(CanNum > 0){
                Console.WriteLine("Read CanMsgNum = {0}",CanNum);
                for(int i=0;i<CanNum;i++){
                    CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)msgPt + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_MSG));
                    Console.WriteLine("CanMsg[{0}].ID = 0x{1}",i,CanMsgBuffer[i].ID.ToString("X8"));
                    //Console.WriteLine("CanMsg[{0}].TimeStamp = {1}",i,CanMsgBuffer[i].TimeStamp);
                    Console.Write("CanMsg[{0}].Data = ",i);
                    for(int j=0;j<CanMsgBuffer[i].DataLen;j++){
                        Console.Write("{0} ",CanMsgBuffer[i].Data[j].ToString("X2"));
                    }
                    Console.WriteLine("");
                }
            }else if(CanNum == 0){
                Console.WriteLine("No CAN data!");
            }else{
                Console.WriteLine("Get CAN data error!");
            }
            Console.WriteLine("");
            //将CAN消息数据填充到信号里面
            DBCParser.DBC_SyncCANMsgToValue(DBCHandle,msgPt,CanNum);
            //获取信号值并打印出来
            StringBuilder ValueStr = new StringBuilder(32);
            DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), ValueStr);
            Console.WriteLine("moto_speed = {0}", ValueStr);
            DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), ValueStr);
            Console.WriteLine("oil_pressure = {0}", ValueStr);
            DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), ValueStr);
            Console.WriteLine("speed_can = {0}", ValueStr);
            //关闭设备
            USB_DEVICE.USB_CloseDevice(DevHandle);
        }
    }
}
